//
// Created by 黄扬航 on 2023/4/19.
//

#include "Snake.h"
#include"Tools.h"
#include"Point.h"
#include"Menu.h"
#include"Control.h"
Tools b;
Point Pointer=Point::getInstance();
int Snake::CurrentScore=0;
int Snake::SnakeSize=3;
Menu Menus;
void Snake::SnakeGrow(Point::Item a) {
    _Snake.emplace_back(a);
    if (Control::HradLevel == 1000) CurrentScore += 10;
    if (Control::HradLevel == 500) CurrentScore += 20;
    if (Control::HradLevel == 100) CurrentScore += 50;
    SnakeSize++;
    Menus.Updata();
}
void Snake::PrintSnake() {
    for (auto& Temp :_Snake)
    {
        b.MoveCursorTo(Temp.X, Temp.Y, 'S');
        Sleep(Control::HradLevel /1000);
    }
}
bool Snake::SnakeMove() {

    Point::Item TempTail;
    TempTail = _Snake.front();
    Point::Item TempTop;
    TempTop = _Snake.back();
    CoordinateControl(TempTail,TempTop,TempTop.Heading);
    if (SnakeStatus(TempTail.X, TempTail.Y) == Grow)    //下个到达的地方如果是食物
    {
        const int Index = TempTail.X + MaxLength * (TempTail.Y);   //Pointer[Index] = TempTail;会直接复写Index点的IsFood，无需修改
        Pointer[Index] = TempTail;
        SnakeGrow(Pointer[Index]);
        b.MoveCursorTo(TempTail.X, TempTail.Y, 'S');
        Sleep(Control::HradLevel / 1000);
        Pointer.ThereIsFood = false;
        return true;
    }
    else if (SnakeStatus(TempTail.X, TempTail.Y) == Died)
        return false;
    else if (SnakeStatus(TempTail.X, TempTail.Y) == Same)
    {
        Pointer[_Snake.front().X + MaxLength * _Snake.front().Y].IsSnake = false;
        b.MoveCursorTo(_Snake.front().X, _Snake.front().Y, ' ');
        Sleep(Control::HradLevel / 1000);
        b.MoveCursorTo(TempTail.X, TempTail.Y, 'S');
        Sleep(Control::HradLevel / 1000);
        _Snake.pop_front();
        _Snake.emplace_back(TempTail);
        return true;
    }
}
bool Snake::SnakeMove(int Operation) {
    Point::Item TempTail,TempTop;
    TempTail = _Snake.front(); TempTop = _Snake.back(); TempTail.IsSnake = false;
    CoordinateControl(TempTail,TempTop,Operation);
    if (SnakeStatus(TempTail.X, TempTail.Y) == Grow)    //下个到达的地方如果是食物
    {
        const int Index = TempTail.X + MaxLength * (TempTail.Y);
        CoordinateControl(TempTail,Index,TempTail.Heading);
        b.MoveCursorTo(TempTail.X, TempTail.Y, 'S');
        Sleep(Control::HradLevel / 1000);
        Pointer.ThereIsFood = false;
        return true;
    }
    else if (SnakeStatus(TempTail.X, TempTail.Y) == Died)
    {
        return false;
    }
    else if (SnakeStatus(TempTail.X, TempTail.Y) == Same)
    {
        Pointer[_Snake.front().X + MaxLength * _Snake.front().Y].IsSnake = false;
        b.MoveCursorTo(_Snake.front().X, _Snake.front().Y, ' ');
        Sleep(Control::HradLevel / 1000);
        b.MoveCursorTo(TempTail.X, TempTail.Y, 'S');
        Sleep(Control::HradLevel / 1000);
        _Snake.pop_front(); _Snake.emplace_back(TempTail);
        return true;
    }
}
SnakeStatusBack Snake::SnakeStatus(int HeadingX, int HeadingY)
{
    if (Pointer[HeadingX + MaxLength * HeadingY].IsFood)
        return Grow;
    else if (Pointer[HeadingX + MaxLength * HeadingY].IsBorder||Pointer[HeadingX + MaxLength * HeadingY].IsSnake)
        return Died;
    else return Same;
}

bool Snake::CoordinateControl(Point::Item &TempTail, Point::Item &TempTop,int Operation) {
    switch (Operation)
    {
        case SnakeMove::Up:
        {
            TempTail = TempTop;
            TempTail.Y--;
        }break;
        case SnakeMove::Down:
        {
            TempTail = TempTop;
            TempTail.Y++;
        }break;
        case SnakeMove::Left:
        {
            TempTail = TempTop;
            TempTail.X--;
        }break;
        case SnakeMove::Right:
        {
            TempTail = TempTop;
            TempTail.X++;
        }break;
        case 72: //上
        {
            TempTail = TempTop;
            TempTail.Y--;
            TempTail.Heading = SnakeMove::Up;
        }break;
        case 80:  //下
        {
            TempTail = TempTop;
            TempTail.Y++;
            TempTail.Heading = SnakeMove::Down;
        }break;
        case 75: //左
        {
            TempTail = TempTop;
            TempTail.X--;
            TempTail.Heading = SnakeMove::Left;
        }break;
        case 77: //右
        {
            TempTail = TempTop;
            TempTail.X++;
            TempTail.Heading = SnakeMove::Right;
        }break;
        default:break;
    }
    return true;
}

bool Snake::CoordinateControl(Point::Item &TempTail, int Index, int Operation) {
    switch (Operation)    //Pointer[Index] = TempTail;会直接复写Index点的IsFood，无需修改
    {
        case SnakeMove::Up:
        {
            Pointer[Index] = TempTail;
            Pointer[Index].Heading = SnakeMove::Up;
            SnakeGrow(Pointer[Index]);
        }break;
        case SnakeMove::Down:
        {
            Pointer[Index] = TempTail;
            Pointer[Index].Heading = SnakeMove::Down;
            SnakeGrow(Pointer[Index]);
        }break;
        case SnakeMove::Left:
        {
            Pointer[Index] = TempTail;
            Pointer[Index].Heading = SnakeMove::Left;
            SnakeGrow(Pointer[Index]);
        }break;
        case SnakeMove::Right:
        {
            Pointer[Index] = TempTail;
            Pointer[Index].Heading = SnakeMove::Right;
            SnakeGrow(Pointer[Index]);
        }break;
        default:break;
    }
    return true;
}
